#!/usr/bin/python

import unittest, sys, os, os.path as path

if __name__ == "__main__":
    """Hack around the python import system to
    allow us to import from a parent directory"""
    FPATH = path.normpath(path.join(os.getcwd(), __file__))
    IPATH = path.normpath(path.join(path.dirname(FPATH),"../../"))
    sys.path.append(IPATH)

from gehyra.common.cidr import CIDR
from gehyra.common.ipv4 import IPv4Address as I4

class TestCIDRConstructor(unittest.TestCase):

    def test_implicit_none(self):
        self.assertRaises(TypeError, CIDR, None)

    def test_explicit_none(self):
        self.assertRaises(TypeError, CIDR, None, None)
        
    def test_tuple_short(self):
        self.assertRaises(ValueError, CIDR, ("foo",))

    def test_tuple_long(self):
        self.assertRaises(ValueError, CIDR, ("foo", "bar", "baz"))

    def test_tuple_invalid_types1(self):
        self.assertRaises(TypeError, CIDR, (1, 2))

    def test_tuple_invalid_types2(self):
        self.assertRaises(TypeError, CIDR, ("0.0.0.0", "foo"))

    def test_tuple_invalid_value1(self):
        self.assertRaises(ValueError, CIDR, ("foo", "bar"))

    def test_tuple_second_parameter(self):
        self.assertRaises(TypeError, CIDR, ("0.0.0.0", 32), "bar")

    def test_tuple_ipv4_prefix_negative(self):
        self.assertRaises(ValueError, CIDR, ("0.0.0.0", -1))

    def test_tuple_ipv4_prefix_too_big(self):
        self.assertRaises(ValueError, CIDR, ("0.0.0.0", 33))

    def test_tuple_ipv4_prefix_min(self):
        c = CIDR(("0.0.0.0", 0))
        self.assertEqual(c.addr.ip, 0)
        self.assertEqual(c.prefix, 0)

    def test_tuple_ipv4_prefix_max(self):
        c = CIDR(("0.0.0.0", 32))
        self.assertEqual(c.addr.ip, 0)
        self.assertEqual(c.prefix, 32)


    def test_tuple_ipv4_long_prefix_negative(self):
        self.assertRaises(ValueError, CIDR, ("0.0.0.0", -1L))

    def test_tuple_ipv4_long_prefix_too_big(self):
        self.assertRaises(ValueError, CIDR, ("0.0.0.0", 33L))

    def test_tuple_ipv4_long_prefix_min(self):
        c = CIDR(("0.0.0.0", 0L))
        self.assertEqual(c.addr.ip, 0)
        self.assertEqual(c.prefix, 0)

    def test_tuple_ipv4_long_prefix_max(self):
        c = CIDR(("0.0.0.0", 32L))
        self.assertEqual(c.addr.ip, 0)
        self.assertEqual(c.prefix, 32)


    ## todo: duplicate these for v6
    def test_v4_int_invalid_type(self):
        self.assertRaises(TypeError, CIDR, I4(0), "foo")

    def test_v4_int_prefix_negative(self):
        self.assertRaises(ValueError, CIDR, I4(0), -1)

    def test_v4_int_prefix_large(self):
        self.assertRaises(ValueError, CIDR, I4(0), 33)

    def test_v4_int_prefix_min(self):
        c = CIDR(I4(0), 0)
        self.assertEqual(c.addr.ip, 0)
        self.assertEqual(c.prefix, 0)

    def test_v4_int_prefix_max(self):
        c = CIDR(I4(0), 32)
        self.assertEqual(c.addr.ip, 0)
        self.assertEqual(c.prefix, 32)

    def test_v4_long_prefix_negative(self):
        self.assertRaises(ValueError, CIDR, I4(0), -1L)

    def test_v4_long_prefix_large(self):
        self.assertRaises(ValueError, CIDR, I4(0), 33L)

    def test_v4_long_prefix_min(self):
        c = CIDR(I4(0), 0L)
        self.assertEqual(c.addr.ip, 0)
        self.assertEqual(c.prefix, 0)

    def test_v4_long_prefix_max(self):
        c = CIDR(I4(0), 32L)
        self.assertEqual(c.addr.ip, 0)
        self.assertEqual(c.prefix, 32)
        
    def test_str_int_invalid_addr(self):
        self.assertRaises(ValueError, CIDR, "0", 0)

    ## todo: duplicate these for v6
    def test_str4_int_prefix_negative(self):
        self.assertRaises(ValueError, CIDR, "0.0.0.0", -1)

    def test_str4_int_prefix_min(self):
        c = CIDR("0.0.0.0", 0)
        self.assertEqual(c.addr.ip, 0)
        self.assertEqual(c.prefix, 0)

    def test_str4_int_prefix_max(self):
        c = CIDR("0.0.0.0", 32)
        self.assertEqual(c.addr.ip, 0)
        self.assertEqual(c.prefix, 32)

    def test_str4_int_prefix_large(self):
        self.assertRaises(ValueError, CIDR, "0.0.0.0", 33)

    def test_str4_long_prefix_negative(self):
        self.assertRaises(ValueError, CIDR, "0.0.0.0", -1L)

    def test_str4_long_prefix_min(self):
        c = CIDR("0.0.0.0", 0L)
        self.assertEqual(c.addr.ip, 0)
        self.assertEqual(c.prefix, 0)

    def test_str4_long_prefix_max(self):
        c = CIDR("0.0.0.0", 32L)
        self.assertEqual(c.addr.ip, 0)
        self.assertEqual(c.prefix, 32)

    def test_str4_long_prefix_large(self):
        self.assertRaises(ValueError, CIDR, "0.0.0.0", 33L)

    def test_cidr_second_parameter(self):
        self.assertRaises(TypeError, CIDR, "0.0.0.0/0", "foo")

    def test_cidr_invalid1(self):
        self.assertRaises(ValueError, CIDR, "0.0.0/0")

    def test_cidr_invalid2(self):
        self.assertRaises(ValueError, CIDR, "0.0.0.0.0/0")

    def test_cidr_invalid3(self):
        self.assertRaises(ValueError, CIDR, "0.0.0.0/0/0")

    ## todo: duplicate these for v6
    def test_cidr4_prefix_negative(self):
        self.assertRaises(ValueError, CIDR, "0.0.0.0/-1")

    def test_cidr4_int_prefix_min(self):
        c = CIDR("0.0.0.0/0")
        self.assertEqual(c.addr.ip, 0)
        self.assertEqual(c.prefix, 0)

    def test_cidr4_int_prefix_max(self):
        c = CIDR("0.0.0.0/32")
        self.assertEqual(c.addr.ip, 0)
        self.assertEqual(c.prefix, 32)

    def test_cidr4_int_prefix_large(self):
        self.assertRaises(ValueError, CIDR, "0.0.0.0/33")

class TestCIDREqualityBetweenSameCIDR(unittest.TestCase):

    """These are importent to lay out in a sensible fashon.
    Because __eq__ it not nesseserally considered by python the logical inverse
    of __ne__, we have to manually reintroduce that constraint.

    As a result, for each locally different test, there should be 4 asserts

    assertTrue(a == b)
    assertTrue(b == a) (to test commutivity of the operation)
      and
    assertFalse(a != b) (to test that == is the logical inverse of !=)
    assertFalse(b != a) (and commutivity again)
    """

    def test_cidr_eq_cidr(self):

        c1 = CIDR("0.0.0.0", 0)
        c2 = CIDR("0.0.0.0", 0)
        
        self.assertTrue(c1 == c2)
        self.assertTrue(c2 == c1)
        self.assertFalse(c1 != c2)
        self.assertFalse(c2 != c1)

    def test_cidr_eq_str(self):

        c = CIDR("0.0.0.0", 0)
        s = "0.0.0.0/0"

        self.assertTrue(c == s)
        self.assertTrue(s == c)
        self.assertFalse(c != s)
        self.assertFalse(s != c)

    def test_cidr_eq_tuple(self):

        c = CIDR("1.2.3.4/5")
        t = ("1.2.3.4",5)

        self.assertTrue(c == t)
        self.assertTrue(t == c)
        self.assertFalse(c != t)
        self.assertFalse(t != c)

if __name__ == "__main__":
    unittest.main()

